package com.rzjm.exercise.common.utils;

import com.rzjm.exercise.common.exception.FileException;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * 文件相关的工具类
 * 
 */
public final class FileUtils {
    public static final String FILE_ROOT_DIR_NAME = "files";
    
    private static String INJAR_FILE_SYMBOL = "!/BOOT-INF/classes!/";
    
    /**
     * 获取文件名的扩展名
     * 
     * @param fileName
     *            文件名
     * @return 扩展名
     */
    public static final String getFileExtension(String fileName) {
        if (StringUtils.isEmpty(fileName) || fileName.indexOf(".") == -1 || StringUtils.endsWith(fileName, ".")) {
            return "";
        }
        
        String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1);
        
        if (fileExt.length() > 6) { // it should not be an extension
            return "";
        }
        return fileExt;
    }
    
    /**
     * 删除文件或文件夹，如果是文件夹，将会删除所有所属的文件和文件夹
     */
    public static void deleteRecursively(Path path) {
        if (Files.isDirectory(path)) {
            try {
                Files.list(path).forEach(p -> deleteRecursively(p));
                
                Files.deleteIfExists(path);
            } catch (IOException ioe) {
                throw new FileException(ioe);
            }
        } else {
            try {
                Files.deleteIfExists(path);
            } catch (IOException ioe) {
                throw new FileException(ioe);
            }
        }
    }
    
    public static void deleteQuietly(File file) {
        if (file != null) {
            try {
                file.deleteOnExit();
            } catch (Exception ex) {
                /* ignore */
            }
        }
    }
    
    /**
     * 获取操作系统的临时文件夹
     * 
     * @return 系统的临时文件夹
     */
    public static final File getSystemTempDirectory() {
        return new File(System.getProperty("java.io.tmpdir"));
    }
    
    /**
     * 指定的{@code url}是否是在jar内部的
     */
    public static final boolean isInJarURL(URL url) {
        return StringUtils.contains(url.getPath(), INJAR_FILE_SYMBOL);
    }
    
    public static final String makeValidFilename(String name) {
        StringBuilder sb = new StringBuilder();
        
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            
            switch(c) {
                case ' ':
                    sb.append("_");
                    break;
                case '\\':
                case '/':
                case ':':
                case '<':
                case '>':
                case '|':
                case '?':
                case '*':
                case '"':
                    break;
                default:
                    sb.append(c);
                    break;
            }
        }
        
        return sb.toString();
    }


    /**
     * 输出指定文件的byte数组
     *
     * @param filePath 文件路径
     * @param os 输出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
//            if (!file.exists())
//            {
//                throw new FileNotFoundException(filePath);
//            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除文件
     *
     * @param filePath 文件
     * @return
     */
    public static boolean deleteFile(String filePath)
    {
        boolean flag = false;
        File file = new File(filePath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists())
        {
            file.delete();
            flag = true;
        }
        return flag;
    }
    
    /**
     * 将文件的字符集转化成指定的字符集
     */
    public static final void encode(String srcFile, String destFile, Charset targetCharset) {
        try (FileInputStream fis = new FileInputStream(srcFile);
                DataInputStream in = new DataInputStream(fis);) {
            BufferedReader d = new BufferedReader(new InputStreamReader(in, EncodingUtils.detect(srcFile)));
            
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = d.readLine()) != null) {
                if (sb.length() != 0) {
                    sb.append(System.lineSeparator());
                }
                
                sb.append(line);
            }
            
            File outFile = new File(destFile);
            try {
                Files.createDirectories(outFile.getParentFile().toPath());
                
                outFile.createNewFile();
            } catch (IOException ioe) {
                throw new FileException(ioe);
            }
            
            try (Writer ow = new OutputStreamWriter(new FileOutputStream(outFile), targetCharset)) {
                ow.write(sb.toString());
            }
        } catch (IOException ioe) {
            throw new FileException(ioe);
        }
    }


    public static HttpServletResponse download(String path, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return response;
    }
}
